﻿using System;
using System.Data;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using JTLeigh.Commerce.Spencer.Core.Common.UnitTests.Entities;

namespace JTLeigh.Commerce.Spencer.Core.Data.UnitTests
{

	/// <summary>
	/// Unit tests for the <see cref="RelationsProviderTools"/> class.
	/// </summary>
	[TestClass]
	public class RelationsProviderToolsFixture
	{

		#region Fields

        private const string TestItemIdField = "AttributeId";

		private static readonly DataTable TestAssociationTable;
		private static readonly DataTable TestAttributeDisassociationTable;

		private static readonly Guid TestAttributeId = Guid.NewGuid();
		private static readonly DateTime TestStartDate = new DateTime(2008, 06, 01);
		private static readonly DateTime TestFinishDate = new DateTime(2008, 06, 02);

		#endregion // Fields

		#region Constructors

		/// <summary>
		/// Initializes static fields on <see cref="RelationsProviderTools"/>.
		/// </summary>
		[SuppressMessage("Microsoft.Performance", "CA1810:InitializeReferenceTypeStaticFieldsInline", Justification = "These fields can't be initialized at declaration.")]
		static RelationsProviderToolsFixture()
		{
			TestAssociationTable = new DataTable
			{
				Locale = CultureInfo.InvariantCulture,
			};
			TestAssociationTable.Columns.Add(new DataColumn(TestItemIdField, typeof(Guid)));
			TestAssociationTable.Columns.Add(new DataColumn(RelationsProviderTools.ColumnName.AttributeAssociation.StartDate, typeof(DateTime)));
			TestAssociationTable.Columns.Add(new DataColumn(RelationsProviderTools.ColumnName.AttributeAssociation.FinishDate, typeof(DateTime)));

			TestAttributeDisassociationTable = new DataTable
			{
				Locale = CultureInfo.InvariantCulture,
			};
			TestAttributeDisassociationTable.Columns.Add(new DataColumn(TestItemIdField, typeof(Guid)));
			TestAttributeDisassociationTable.Columns.Add(new DataColumn(RelationsProviderTools.ColumnName.AttributeDisassociation.StartDate, typeof(DateTime)));
			TestAttributeDisassociationTable.Columns.Add(new DataColumn(RelationsProviderTools.ColumnName.AttributeDisassociation.FinishDate, typeof(DateTime)));
		}

		#endregion // Constructors

		#region Methods

		#region ReadAssociation

		/// <summary>
		/// Ensures <see cref="RelationsProviderTools.ReadAssociation"/> reads all of the
		/// association fields from the reader.
		/// </summary>
		[TestMethod]
		public void TestReadAssociationWithAllFields()
		{
			DataTable table;
			IDataReader reader;
			TestAssociation association;

			table = TestAssociationTable.Clone();
			table.Rows.Add(TestAttributeId, TestStartDate, TestFinishDate);

			reader = new DataTableReader(table);
			reader.Read();

			association = new TestAssociation();

			RelationsProviderTools.ReadAssociation(reader, TestItemIdField, association);

			Assert.AreEqual(TestAttributeId, association.AssociatedItemId);
			Assert.AreEqual(TestStartDate, association.StartDate);
			Assert.AreEqual(TestFinishDate, association.FinishDate);
		}

		/// <summary>
		/// Ensures <see cref="RelationsProviderTools.ReadAssociation"/> reads all of the
		/// association fields from the reader and can handle the <see langword="null"/> fields.
		/// </summary>
		[TestMethod]
		public void TestReadAssociationWithNullFields()
		{
			DataTable table;
			IDataReader reader;
			TestAssociation association;

			table = TestAssociationTable.Clone();
			table.Rows.Add(TestAttributeId, TestStartDate, null);
			
			reader = new DataTableReader(table);
			reader.Read();

			association = new TestAssociation();

			RelationsProviderTools.ReadAssociation(reader, TestItemIdField, association);

			Assert.AreEqual(TestAttributeId, association.AssociatedItemId);
			Assert.AreEqual(TestStartDate, association.StartDate);
			Assert.IsNull(association.FinishDate);
		}

		#endregion // ReadAssociation

		#region ReadDisassociation

		/// <summary>
		/// Ensures <see cref="RelationsProviderTools.ReadDisassociation"/> reads all of 
		/// the disassociation fields from the reader.
		/// </summary>
		[TestMethod]
		public void TestReadDisassociationWithAllFields()
		{
			DataTable table;
			IDataReader reader;
			TestDisassociation disassociation;

			table = TestAttributeDisassociationTable.Clone();
			table.Rows.Add(TestAttributeId, TestStartDate, TestFinishDate);

			reader = new DataTableReader(table);
			reader.Read();

			disassociation = new TestDisassociation();

			RelationsProviderTools.ReadDisassociation(reader, TestItemIdField, disassociation);

			Assert.AreEqual(TestAttributeId, disassociation.DisassociatedItemId);
			Assert.AreEqual(TestStartDate, disassociation.StartDate);
			Assert.AreEqual(TestFinishDate, disassociation.FinishDate);
		}

		/// <summary>
		/// Ensures <see cref="RelationsProviderTools.ReadDisassociation"/> reads all of 
		/// the disassociation fields from the reader and can handle the <see langword="null"/> fields.
		/// </summary>
		[TestMethod]
		public void TestReadDisassociationWithNullFields()
		{
			DataTable table;
			IDataReader reader;
			TestDisassociation disassociation;

			table = TestAttributeDisassociationTable.Clone();
			table.Rows.Add(TestAttributeId, TestStartDate, null);

			reader = new DataTableReader(table);
			reader.Read();

			disassociation = new TestDisassociation();

			RelationsProviderTools.ReadDisassociation(reader, TestItemIdField, disassociation);

			Assert.AreEqual(TestAttributeId, disassociation.DisassociatedItemId);
			Assert.AreEqual(TestStartDate, disassociation.StartDate);
			Assert.IsNull(disassociation.FinishDate);
		}

		#endregion // ReadDisassociation

		#endregion // Methods

	}

}
